package com.vxdata.common.filter;

import com.vxdata.common.constant.HttpStatus;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 域名校验过滤器
 */
public class RefererFilter implements Filter {

    /**
     * 是否启用
     */
    private boolean enable = true;

    /**
     * 忽略的URL
     */
    private List<String> excludes;

    /**
     * 前缀
     */
    private String refererPrefix;

    /**
     * 初始化一个RefererFilter 对象
     *
     * @param enable        是否开启域名校验
     * @param refererPrefix 允许访问的域名
     * @param excludes      白名单
     */
    public RefererFilter(boolean enable, String refererPrefix, List<String> excludes) {
        this.refererPrefix = refererPrefix;
        this.enable = enable;
        this.excludes = excludes;
    }

    public RefererFilter(String refererPrefix, boolean enable) {
        this(enable, refererPrefix, null);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        // 不启用或者已忽略的URL不拦截
        if (!enable || isExcludeUrl(req.getServletPath())) {
            chain.doFilter(req, resp);
            return;
        }

        String referer = req.getHeader("Referer");
        String serverName = request.getServerName();
        //System.out.println("======================== Referer : " + referer + ", serverName : " + serverName);
        //配置可通过filter的前缀
        boolean flag = false;
        if (referer != null) {
            if (refererPrefix != null) {
                String[] split = refererPrefix.split(",");
                for (String prefix : split) {
                    boolean prefixYes = referer.startsWith(prefix);
                    if (prefixYes) {
                        flag = true;
                        break;
                    }
                }
            }
        }
        if (flag || (referer != null && referer.contains(serverName))) {
            chain.doFilter(req, resp);
        } else {
            resp.setStatus(HttpStatus.NOT_FOUND);
            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().write("系统不支持当前域名的访问！");
        }
    }

    @Override
    public void destroy() {

    }

    /**
     * 判断是否为忽略的URL
     *
     * @param url URL路径
     * @return true-忽略，false-过滤
     */
    private boolean isExcludeUrl(String url) {
        if (excludes == null || excludes.isEmpty()) {
            return false;
        }
        return excludes.stream().map(pattern -> Pattern.compile("^" + pattern)).map(p -> p.matcher(url))
                .anyMatch(Matcher::find);
    }

}

